package com.dayu.tcp.service;


import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author yehangtech
 * @date 2025/4/6 17:19
 * @description 自定义线程工厂
 */
public class BasicThreadFactory implements ThreadFactory {

    public static class Builder implements com.dayu.tcp.common.Builder<BasicThreadFactory> {

        private ThreadFactory factory;

        private Thread.UncaughtExceptionHandler exceptionHandler;

        private String namingPattern;

        private Integer priority;

        private Boolean daemon;

        @Override
        public BasicThreadFactory build() {
            final BasicThreadFactory factory = new BasicThreadFactory(this);
            reset();
            return factory;
        }

        public Builder daemon(final boolean daemon) {
            this.daemon = daemon;
            return this;
        }

        public Builder namingPattern(final String namingPattern) {
            this.namingPattern = Objects.requireNonNull(namingPattern, "pattern");
            return this;
        }

        public Builder priority(final int priority) {
            this.priority = priority;
            return this;
        }

        public void reset() {
            factory = null;
            exceptionHandler = null;
            namingPattern = null;
            priority = null;
            daemon = null;
        }

        public Builder uncaughtExceptionHandler(
                final Thread.UncaughtExceptionHandler exceptionHandler) {
            this.exceptionHandler = Objects.requireNonNull(exceptionHandler, "handler");
            return this;
        }

        public Builder wrappedFactory(final ThreadFactory factory) {
            this.factory = Objects.requireNonNull(factory, "factory");
            return this;
        }
    }

    private final AtomicLong threadCounter;

    private final ThreadFactory wrappedFactory;

    private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler;

    private final String namingPattern;

    private final Integer priority;

    private final Boolean daemon;

    private BasicThreadFactory(final Builder builder) {
        wrappedFactory = builder.factory != null ? builder.factory : Executors.defaultThreadFactory();
        namingPattern = builder.namingPattern;
        priority = builder.priority;
        daemon = builder.daemon;
        uncaughtExceptionHandler = builder.exceptionHandler;
        threadCounter = new AtomicLong();
    }

    public final Boolean getDaemonFlag() {
        return daemon;
    }

    public final String getNamingPattern() {
        return namingPattern;
    }

    public final Integer getPriority() {
        return priority;
    }

    public long getThreadCount() {
        return threadCounter.get();
    }

    public final Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler;
    }

    public final ThreadFactory getWrappedFactory() {
        return wrappedFactory;
    }

    private void initializeThread(final Thread thread) {
        if (getNamingPattern() != null) {
            final Long count = threadCounter.incrementAndGet();
            thread.setName(String.format(getNamingPattern(), count));
        }
        if (getUncaughtExceptionHandler() != null) {
            thread.setUncaughtExceptionHandler(getUncaughtExceptionHandler());
        }
        if (getPriority() != null) {
            thread.setPriority(getPriority());
        }
        if (getDaemonFlag() != null) {
            thread.setDaemon(getDaemonFlag());
        }
    }

    @Override
    public Thread newThread(final Runnable runnable) {
        final Thread thread = getWrappedFactory().newThread(runnable);
        initializeThread(thread);
        return thread;
    }
}